package com.cskaoyan.javase.oop3._0abstract._0introduction;

/**
 * 抽象类的引入
 * 以下猫狗继承案例，是一个非常基础的继承语法的代码。
 * 思考一下Animal类的继承体系，有什么问题吗？
 *
 * 从以下两个角度分析：
 *      1.从代码角度上，有没有冗余代码？
 *          Animal类的shout方法的方法体其实是不需要的
 *          可以把它去掉
 *          Animal类的shout方法就是用来被继承,被重写的
 *
 *      2.从设计角度上，在这个案例中，会存在一个动物对象吗？
 *      不存在,我们创建的对象都是具体的动物对象
 *      没有Animal对象
 *
 * 所以综上，我们提出两个改进的方向：
 *      1.Animal类就是一个抽象的概念
 *      这个类就是用来被继承的,不是用来创建对象的
 *      Animal类就是作为顶层抽象祖先类而存在的，不需要创建对象，于是干脆不要创建对象了。
 *
 *      2.Animal类当中的shout方法不需要方法体，仅用于作为被继承和重写一个方法声明。
 *      抽象概念没有办法描述行为.
 *
 * 一个方法要么有方法体,要么就必须声明为抽象方法
 * ps: 本地方法也没有方法,但这不在讨论之内.
 *
 * 抽象方法的定义:
 * [访问权限修饰符] abstract 返回值类型 方法名(形参列表);
 * 抽象方法不需要具体实现,所以没有大括号,但是要有";"
 *
 * 按照上述语法改进方法后:
 * Abstract method in non-abstract class
 * Class 'Animal' must either be declared abstract or implement abstract method 'shout()' in 'Animal'
 * 抽象方法不可能存在于普通类中
 * 普通类没有抽象方法
 * 抽象方法必须定义在抽象类中。
 *
 * 抽象类的定义：
 * [访问权限修饰符] abstract class 类名{
 *     // 类体
 * }
 *
 *
 *
 * @since 16:09
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 'Animal' is abstract; cannot be instantiated
        // 抽象类不能实例化，不能创建对象
        // new Animal();

        Animal a;
        a = new Cat();
        a.shout();
        a = new Dog();
        a.shout();
    }
}

abstract class Animal {
    // Missing method body, or declare abstract
    public abstract void shout();
}

class Cat extends Animal {
    // 该方法重写自父类的抽象方法
    @Override
    public void shout() {
        System.out.println("猫叫");
    }
}

class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}